#include <QFile>
#include <QTextStream>
#include <QDir>
#include <QInputDialog>
#include <QComboBox>
#include <QGraphicsOpacityEffect>
#include <QPropertyAnimation>
#include <QMessageBox>
#include <QVersionNumber>
#include <QDateTime>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QFileDialog>
#include <QMenu>

#include "qrsagsquerydialog.h"
#include "ui_QRSAGSQueryDialog.h"
#include "qgisapp.h"
#include "qgslogger.h"
#include "qgsexpression.h"
#include "qgsexpressionfunction.h"
#include "qgsexpressionnodeimpl.h"
#include "qgsapplication.h"
#include "qgspythonrunner.h"
#include "qgsgeometry.h"
#include "qgsfeature.h"
#include "qgsfeatureiterator.h"
#include "qgsvectorlayer.h"
#include "qgssettings.h"
#include "qgsproject.h"
#include "qgsrelation.h"
#include "qgsexpressioncontextutils.h"
#include "qgsfieldformatterregistry.h"
#include "qgsfieldformatter.h"
#include "qgsexpressionstoredialog.h"
#include "qgsmapcanvas.h"

QRSAGSQueryDialog::QRSAGSQueryDialog(QgsVectorLayer *currentVectorLayer, QWidget *parent, Qt::WindowFlags flags) :
    QDialog(parent, flags),
    mVectorLayer(currentVectorLayer),
    ui(new Ui::QRSAGSQueryDialog)
{
    //设置ui的部分内容
    this->setObjectName(QStringLiteral("数据查询:") + mVectorLayer->id());
    ui->setupUi(this);

    //设置图表内容的选择方式，
    ui->mVectorDataTableView->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu);
    ui->mVectorDataTableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
    ui->mVectorDataTableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
    ui->mVectorDataTableView->setSelectionBehavior(QAbstractItemView::SelectRows);
    ui->mVectorDataTableView->setSelectionMode(QAbstractItemView::SingleSelection);

    //双击表格中的行，则定位到图中的目标
    connect(ui->mVectorDataTableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(hightLightSelectedFeature(QModelIndex)));

    mMapcanvas = QgisApp::instance()->mapCanvas();
    //初始化图表和查询的内容
    initTableView();

    //初始化基于属性的简单的查询
    initExpressionBuilderByParameter();

    //初始化基于属性的查询内容
    initExpressionBuilderByDetailedParameter();

    //初始化基于位置的查询内容
    initExpressionBuilderByPosition();

    //构建查询按钮槽函数
    connect(ui->mExpressionQueryDetailButton, SIGNAL(clicked(bool)), this, SLOT(queryByDetailedParameterExpression(bool)));
    connect(ui->mExpressionClearDetailButton, SIGNAL(clicked(bool)), this, SLOT(clearDetailedFilterText(bool)));
    connect(ui->mCloseButton, SIGNAL(clicked(bool)), this, SLOT(closeDialog(bool)));
}

QRSAGSQueryDialog::~QRSAGSQueryDialog()
{
    delete mExpressionTreeMenuProvider;
    delete ui;
}

void QRSAGSQueryDialog::setExpectedOutputFormat(const QString &expected)
{
    ui->lblExpected->setText( expected );
    ui->mExpectedOutputFrame->setVisible( !expected.isNull() );
}

void QRSAGSQueryDialog::initTableView()
{
    //构建数据缓存
    QgsVectorLayerCache *vectorLayerCache = new QgsVectorLayerCache(mVectorLayer, mVectorLayer->featureCount());

    //创建数据模型
    QgsAttributeTableModel *tableModel = new QgsAttributeTableModel(vectorLayerCache, this);
    tableModel->loadLayer();// 一定不要忘记，否则model里面没有图层的属性数据
    mTableModel = tableModel;

    //从图层中获取数据，然后将数据汇总至表格
    QgsAttributeTableFilterModel *tableFilterModel = new QgsAttributeTableFilterModel(mMapcanvas, tableModel, tableModel);
    tableFilterModel->setFilterMode(QgsAttributeTableFilterModel::ShowAll);
    ui->mVectorDataTableView->setModel(tableFilterModel);
    mFilterModel = tableFilterModel;
}

void QRSAGSQueryDialog::initExpressionBuilderByParameter()
{
    ui->mFieldComboBox->clear();

    if(mTableModel == nullptr){
        return;
    }

    QgsFields fields = mTableModel->layer()->fields();
    for(QgsField field : fields){
        ui->mFieldComboBox->addItem(field.name());
    }

//    int rowCount = mFilterModel->rowCount();
//    int columnIndex = ui->mFieldComboBox->currentIndex();
//    QAbstractItemModel *tableModel = ui->mVectorDataTableView->model();
//    for(int i=0; i<rowCount; i++){
//        QString value = tableModel->index(i, columnIndex).data().toString();
//        ui->mValueComboBox->addItem(value);
//    }

    connect(ui->mQueryExpressionLineEdit, SIGNAL(textChanged(QString)), this, SLOT(queryExpressionChanged(QString)));
    connect(ui->mExpressionQueryButton, SIGNAL(clicked(bool)), this, SLOT(queryByParameterExpression(bool)));
    connect(ui->mExpressionClearButton, SIGNAL(clicked(bool)), this, SLOT(clearFilterText(bool)));
}

void QRSAGSQueryDialog::initExpressionBuilderByDetailedParameter()
{
    //初始化 根据属性查询 的内容
    connect( ui->txtExpressionString, &QgsCodeEditorExpression::textChanged, this, &QRSAGSQueryDialog::txtExpressionString_textChanged );
    connect( ui->txtSearchEdit, &QgsFilterLineEdit::textChanged, ui->mExpressionTreeView, &QgsExpressionTreeView::setSearchText );
    connect( ui->mExpressionPreviewWidget, &QgsExpressionPreviewWidget::toolTipChanged, ui->txtExpressionString, &QgsCodeEditorExpression::setToolTip );
    connect( ui->mExpressionPreviewWidget, &QgsExpressionPreviewWidget::expressionParsed, this, &QRSAGSQueryDialog::onExpressionParsed );

    connect( ui->mExpressionPreviewWidget, &QgsExpressionPreviewWidget::expressionParsed, this, &QRSAGSQueryDialog::expressionParsed ); // signal-to-signal
    connect( ui->mExpressionPreviewWidget, &QgsExpressionPreviewWidget::parserErrorChanged, this, &QRSAGSQueryDialog::parserErrorChanged ); // signal-to-signal
    connect( ui->mExpressionPreviewWidget, &QgsExpressionPreviewWidget::evalErrorChanged, this, &QRSAGSQueryDialog::evalErrorChanged ); // signal-to-signal

    connect( ui->mExpressionTreeView, &QgsExpressionTreeView::expressionItemDoubleClicked, this, &QRSAGSQueryDialog::insertExpressionText );

    mExpressionTreeMenuProvider = new ExpressionTreeMenuProvider( this );
    ui->mExpressionTreeView->setMenuProvider( mExpressionTreeMenuProvider );

    const auto pushButtons { ui->mOperatorsGroupBox->findChildren<QPushButton *>() };
    for ( QPushButton *button : pushButtons )
    {
        connect( button, &QAbstractButton::pressed, this, &QRSAGSQueryDialog::operatorButtonClicked );
    }

    ui->txtSearchEdit->setShowSearchIcon( true );
    ui->txtSearchEdit->setPlaceholderText( tr( "Search..." ) );
    ui->txtExpressionString->setWrapMode( QsciScintilla::WrapWord );

    // Note: If you add a indicator here you should add it to clearErrors method if you need to clear it on text parse.
    ui->txtExpressionString->indicatorDefine( QgsCodeEditor::SquiggleIndicator, QgsExpression::ParserError::FunctionUnknown );
    ui->txtExpressionString->indicatorDefine( QgsCodeEditor::SquiggleIndicator, QgsExpression::ParserError::FunctionWrongArgs );
    ui->txtExpressionString->indicatorDefine( QgsCodeEditor::SquiggleIndicator, QgsExpression::ParserError::FunctionInvalidParams );
    ui->txtExpressionString->indicatorDefine( QgsCodeEditor::SquiggleIndicator, QgsExpression::ParserError::FunctionNamedArgsError );
#if defined(QSCINTILLA_VERSION) && QSCINTILLA_VERSION >= 0x20a00
    ui->txtExpressionString->indicatorDefine( QgsCodeEditor::TriangleIndicator, QgsExpression::ParserError::Unknown );
#else
    ui->txtExpressionString->indicatorDefine( QgsCodeEditor::SquiggleIndicator, QgsExpression::ParserError::Unknown );
#endif

    // Set all the error markers as red. -1 is all.
    ui->txtExpressionString->setIndicatorForegroundColor( QColor( Qt::red ), -1 );
    ui->txtExpressionString->setIndicatorHoverForegroundColor( QColor( Qt::red ), -1 );
    ui->txtExpressionString->setIndicatorOutlineColor( QColor( Qt::red ), -1 );

    // Hidden function markers.
    ui->txtExpressionString->indicatorDefine( QgsCodeEditor::HiddenIndicator, FUNCTION_MARKER_ID );
    ui->txtExpressionString->setIndicatorForegroundColor( QColor( Qt::blue ), FUNCTION_MARKER_ID );
    ui->txtExpressionString->setIndicatorHoverForegroundColor( QColor( Qt::blue ), FUNCTION_MARKER_ID );
    ui->txtExpressionString->setIndicatorHoverStyle( QgsCodeEditor::DotsIndicator, FUNCTION_MARKER_ID );

    //    connect( ui->txtExpressionString, &QgsCodeEditorExpression::indicatorClicked, this, &QRSAGSQueryDialog::indicatorClicked );
    ui->txtExpressionString->setAutoCompletionCaseSensitivity( false );
    ui->txtExpressionString->setAutoCompletionSource( QsciScintilla::AcsAPIs );
    ui->txtExpressionString->setCallTipsVisible( 0 );

    setExpectedOutputFormat( QString() );

    QgsExpressionContext context( QgsExpressionContextUtils::globalProjectLayerScopes( mVectorLayer ) );

    setExpressionContext(context);
    setLayer( mVectorLayer );

    QgsDistanceArea distanceArea;
    distanceArea.setSourceCrs(mVectorLayer->crs(), QgsProject::instance()->transformContext());
    distanceArea.setEllipsoid(QgsProject::instance()->ellipsoid());
    ui->mExpressionPreviewWidget->setGeomCalculator(distanceArea);
    //    setExpressionText( startText );
}

void QRSAGSQueryDialog::initExpressionBuilderByPosition()
{
    //当文本发生变化时，修改清空按钮的功能
    connect(ui->mPointLonLineEdit, SIGNAL(textChanged(QString)), this, SLOT(pointPositionValueChanged(QString)));
    connect(ui->mPointLatLineEdit, SIGNAL(textChanged(QString)), this, SLOT(pointPositionValueChanged(QString)));

    connect(ui->mRectangleWLonLineEdit, SIGNAL(textChanged(QString)), this, SLOT(rectanglePositionValueChanged(QString)));
    connect(ui->mRectangleELonLineEdit, SIGNAL(textChanged(QString)), this, SLOT(rectanglePositionValueChanged(QString)));
    connect(ui->mRectangleNLatLineEdit, SIGNAL(textChanged(QString)), this, SLOT(rectanglePositionValueChanged(QString)));
    connect(ui->mRectangleSLatLineEdit, SIGNAL(textChanged(QString)), this, SLOT(rectanglePositionValueChanged(QString)));

    //建立清空功能
    connect(ui->mPointClearButton, SIGNAL(clicked(bool)), this, SLOT(clearPointPosition(bool)));
    connect(ui->mRectangleClearButton, SIGNAL(clicked(bool)), this, SLOT(clearRectanglePosition(bool)));

    //建立查询功能
    connect(ui->mPointQueryButton, SIGNAL(clicked(bool)), this, SLOT(queryByPointPosition()));
    connect(ui->mRectangleQueryButton, SIGNAL(clicked(bool)), this, SLOT(queryByRectanglePosition()));
}

void QRSAGSQueryDialog::clearErrors()
{
    int lastLine = ui->txtExpressionString->lines() - 1;
    // Note: -1 here doesn't seem to do the clear all like the other functions.  Will need to make this a bit smarter.
    ui->txtExpressionString->clearIndicatorRange( 0, 0, lastLine, ui->txtExpressionString->text( lastLine ).length(), QgsExpression::ParserError::Unknown );
    ui->txtExpressionString->clearIndicatorRange( 0, 0, lastLine, ui->txtExpressionString->text( lastLine ).length(), QgsExpression::ParserError::FunctionInvalidParams );
    ui->txtExpressionString->clearIndicatorRange( 0, 0, lastLine, ui->txtExpressionString->text( lastLine ).length(), QgsExpression::ParserError::FunctionUnknown );
    ui->txtExpressionString->clearIndicatorRange( 0, 0, lastLine, ui->txtExpressionString->text( lastLine ).length(), QgsExpression::ParserError::FunctionWrongArgs );
    ui->txtExpressionString->clearIndicatorRange( 0, 0, lastLine, ui->txtExpressionString->text( lastLine ).length(), QgsExpression::ParserError::FunctionNamedArgsError );
}

void QRSAGSQueryDialog::setExpressionContext(const QgsExpressionContext &context)
{
    mExpressionContext = context;
    expressionContextUpdated();
}

void QRSAGSQueryDialog::setLayer(QgsVectorLayer *layer)
{
    ui->mExpressionTreeView->setLayer( layer );
    ui->mExpressionPreviewWidget->setLayer( layer );
    if ( layer )
    {
        mExpressionContext << QgsExpressionContextUtils::layerScope( layer );
        expressionContextUpdated();
        ui->txtExpressionString->setFields( layer->fields() );
    }

    //将筛选条件中，除了“Fields and Values”之外的其他都删除
    QStandardItemModel *model = ui->mExpressionTreeView->model();
    for(int i=0; i<model->rowCount();){
        QStandardItem *item = model->item(i);
        if(item->text() != "Fields and Values"){
            model->removeRow(i);
        }else{
            i++;
        }
    }
}

void QRSAGSQueryDialog::setExpressionText(const QString &expression)
{
    ui->txtExpressionString->setText( expression );
}

void QRSAGSQueryDialog::expressionContextUpdated()
{
    ui->txtExpressionString->setExpressionContext( mExpressionContext );
    ui->mExpressionTreeView->setExpressionContext( mExpressionContext );
    ui->mExpressionPreviewWidget->setExpressionContext( mExpressionContext );
}

bool QRSAGSQueryDialog::isDigitStr(QString value)
{
    if(value.isEmpty()){
        return false;
    }

    bool result = value.contains(QRegExp("[A-Za-z]/g"));
    if(result){
        return false;
    }

    result = value.contains(QRegExp("[+-]?(0|([1-9]\\d*))(\\.\\d+)?"));
    return result;
}

void QRSAGSQueryDialog::createErrorMarkers(QList<QgsExpression::ParserError> errors)
{
    clearErrors();
    for ( const QgsExpression::ParserError &error : errors )
    {
        int errorFirstLine = error.firstLine - 1 ;
        int errorFirstColumn = error.firstColumn - 1;
        int errorLastColumn = error.lastColumn - 1;
        int errorLastLine = error.lastLine - 1;

        // If we have a unknown error we just mark the point that hit the error for now
        // until we can handle others more.
        if ( error.errorType == QgsExpression::ParserError::Unknown )
        {
            errorFirstLine = errorLastLine;
            errorFirstColumn = errorLastColumn - 1;
        }
        ui->txtExpressionString->fillIndicatorRange( errorFirstLine,
                                                     errorFirstColumn,
                                                     errorLastLine,
                                                     errorLastColumn, error.errorType );
    }
}

void QRSAGSQueryDialog::createMarkers(const QgsExpressionNode *inNode)
{
    switch ( inNode->nodeType() )
    {
    case QgsExpressionNode::NodeType::ntFunction:
    {
        const QgsExpressionNodeFunction *node = static_cast<const QgsExpressionNodeFunction *>( inNode );
        ui->txtExpressionString->SendScintilla( QsciScintilla::SCI_SETINDICATORCURRENT, FUNCTION_MARKER_ID );
        ui->txtExpressionString->SendScintilla( QsciScintilla::SCI_SETINDICATORVALUE, node->fnIndex() );
        int start = inNode->parserFirstColumn - 1;
        int end = inNode->parserLastColumn - 1;
        int start_pos = ui->txtExpressionString->positionFromLineIndex( inNode->parserFirstLine - 1, start );
        ui->txtExpressionString->SendScintilla( QsciScintilla::SCI_INDICATORFILLRANGE, start_pos, end - start );
        if ( node->args() )
        {
            const QList< QgsExpressionNode * > nodeList = node->args()->list();
            for ( QgsExpressionNode *n : nodeList )
            {
                createMarkers( n );
            }
        }
        break;
    }
    case QgsExpressionNode::NodeType::ntLiteral:
    {
        break;
    }
    case QgsExpressionNode::NodeType::ntUnaryOperator:
    {
        const QgsExpressionNodeUnaryOperator *node = static_cast<const QgsExpressionNodeUnaryOperator *>( inNode );
        createMarkers( node->operand() );
        break;
    }
    case QgsExpressionNode::NodeType::ntBinaryOperator:
    {
        const QgsExpressionNodeBinaryOperator *node = static_cast<const QgsExpressionNodeBinaryOperator *>( inNode );
        createMarkers( node->opLeft() );
        createMarkers( node->opRight() );
        break;
    }
    case QgsExpressionNode::NodeType::ntColumnRef:
    {
        break;
    }
    case QgsExpressionNode::NodeType::ntInOperator:
    {
        const QgsExpressionNodeInOperator *node = static_cast<const QgsExpressionNodeInOperator *>( inNode );
        if ( node->list() )
        {
            const QList< QgsExpressionNode * > nodeList = node->list()->list();
            for ( QgsExpressionNode *n : nodeList )
            {
                createMarkers( n );
            }
        }
        break;
    }
    case QgsExpressionNode::NodeType::ntCondition:
    {
        const QgsExpressionNodeCondition *node = static_cast<const QgsExpressionNodeCondition *>( inNode );
        for ( QgsExpressionNodeCondition::WhenThen *cond : node->conditions() )
        {
            createMarkers( cond->whenExp() );
            createMarkers( cond->thenExp() );
        }
        if ( node->elseExp() )
        {
            createMarkers( node->elseExp() );
        }
        break;
    }
    case QgsExpressionNode::NodeType::ntIndexOperator:
    {
        break;
    }
    }
}

void QRSAGSQueryDialog::onExpressionParsed(bool state)
{
    clearErrors();

    mExpressionValid = state;
    if ( state )
    {
        createMarkers( ui->mExpressionPreviewWidget->rootNode() );
    }
    else
    {
        createErrorMarkers( ui->mExpressionPreviewWidget->parserErrors() );
    }
}

void QRSAGSQueryDialog::operatorButtonClicked()
{
    QPushButton *button = qobject_cast<QPushButton *>( sender() );
    // Insert the button text or replace selected text
    ui->txtExpressionString->insertText( ' ' + button->text() + ' ' );
    ui->txtExpressionString->setFocus();
}

void QRSAGSQueryDialog::insertExpressionText(const QString &text)
{
    // Insert the expression text or replace selected text
    ui->txtExpressionString->insertText( text );
    ui->txtExpressionString->setFocus();
}

void QRSAGSQueryDialog::txtExpressionString_textChanged()
{
    QString text = ui->txtExpressionString->text();
    ui->mExpressionQueryDetailButton->setEnabled(!text.isEmpty());
    ui->mExpressionPreviewWidget->setExpressionText( text );
}

void QRSAGSQueryDialog::queryExpressionChanged(QString)
{
    QString text = ui->mQueryExpressionLineEdit->text();
    ui->mExpressionQueryButton->setEnabled(!text.isEmpty());
    ui->mExpressionClearButton->setEnabled(!text.isEmpty());
}

void QRSAGSQueryDialog::queryByDetailedParameterExpression(bool)
{
    QString filterString = ui->txtExpressionString->text();
    qDebug() << "---------------" << filterString;
    if (filterString.isEmpty())
    {
        this->setFilterMode(QgsAttributeTableFilterModel::ShowAll);
        return;
    }

    // parse search string and build parsed tree
    QgsExpression filterExpression( filterString );
    if ( filterExpression.hasParserError() )
    {
        ui->mMessageLabel->setText(tr( "Parsing error:" ) + filterExpression.parserErrorString() + "[" + Qgis::Warning + "]");
        return;
    }

    QgsExpressionContext context( QgsExpressionContextUtils::globalProjectLayerScopes( mVectorLayer ) );

    if ( !filterExpression.prepare( &context ) )
    {
        ui->mMessageLabel->setText(tr( "Evaluation error:" ) + filterExpression.parserErrorString() + "[" + Qgis::Warning + "]");
    }

    mFilterModel->setFilterExpression(filterExpression, context);
    mFilterModel->filterFeatures();
    this->setFilterMode(QgsAttributeTableFilterModel::ShowFilteredList);

    //将图层缩放至筛选结果区域
    this->zoomToCurrentFeature();
}

void QRSAGSQueryDialog::queryByParameterExpression(bool)
{
    QString queryExpressionText = ui->mQueryExpressionLineEdit->text();
    if (queryExpressionText.isEmpty())
    {
        this->setFilterMode(QgsAttributeTableFilterModel::ShowAll);
        return;
    }

    // parse search string and build parsed tree
//    QgsExpression filterExpression( "'" + ui->mFieldComboBox->currentText() + "' like '%" +  queryExpressionText + "%'");
    QgsExpression filterExpression( "\"" + ui->mFieldComboBox->currentText() + "\" like '%" +  queryExpressionText + "%'");
    qDebug() << "---------------" << filterExpression;
    if ( filterExpression.hasParserError() )
    {
        ui->mMessageLabel->setText(tr( "Parsing error:" ) + filterExpression.parserErrorString() + "[" + Qgis::Warning + "]");
        return;
    }

    QgsExpressionContext context( QgsExpressionContextUtils::globalProjectLayerScopes( mVectorLayer ) );

    if ( !filterExpression.prepare( &context ) )
    {
        ui->mMessageLabel->setText(tr( "Evaluation error:" ) + filterExpression.parserErrorString() + "[" + Qgis::Warning + "]");
    }

    mFilterModel->setFilterExpression(filterExpression, context);
    mFilterModel->filterFeatures();
    this->setFilterMode(QgsAttributeTableFilterModel::ShowFilteredList);

    //将图层缩放至筛选结果区域
    this->zoomToCurrentFeature();
}

void QRSAGSQueryDialog::clearFilterText(bool)
{
    //清空筛选语句
    ui->mQueryExpressionLineEdit->clear();
    this->setFilterMode(QgsAttributeTableFilterModel::ShowAll);
    if(this->mRubberBand != nullptr){
        this->mRubberBand->reset();
    }
    if(this->mSingleRubberBand != nullptr){
        this->mSingleRubberBand->reset();
    }

    mMapcanvas->zoomToFullExtent();
}

void QRSAGSQueryDialog::clearDetailedFilterText(bool)
{
    //清空筛选语句
    ui->txtExpressionString->clear();
    this->setFilterMode(QgsAttributeTableFilterModel::ShowAll);
    if(this->mRubberBand != nullptr){
        this->mRubberBand->reset();
    }
    if(this->mSingleRubberBand != nullptr){
        this->mSingleRubberBand->reset();
    }

    mMapcanvas->zoomToFullExtent();
}

void QRSAGSQueryDialog::extentChanged()
{
    QgsFeatureRequest r = mTableModel->request();
    if ( mMapcanvas && ( r.filterType() != QgsFeatureRequest::FilterNone || !r.filterRect().isNull() ) )
    {
        QgsRectangle rect = mMapcanvas->mapSettings().mapToLayerCoordinates( mVectorLayer, mMapcanvas->extent() );
        r.setFilterRect( rect );
        mTableModel->setRequest( r );
        mTableModel->loadLayer();
    }
    emit filterChanged();
}

void QRSAGSQueryDialog::filterError(const QString &errorMessage)
{
    QMessageBox::warning(this, tr("Filter Error"),
                         tr("Filter information meet error: ") + errorMessage);
}

void QRSAGSQueryDialog::updateSelectedFeatures()
{
    QgsFeatureRequest r = mTableModel->request();
    if ( r.filterType() == QgsFeatureRequest::FilterNone && r.filterRect().isNull() )
        return; // already requested all features

    r.setFilterFids( mTableModel->layer()->selectedFeatureIds() );
    mTableModel->setRequest( r );
    mTableModel->loadLayer();
    emit filterChanged();
}

void QRSAGSQueryDialog::zoomToCurrentFeature()
{
    QgsFeatureIds featureIds = mFilterModel->filteredFeatures();
    if(featureIds.size() <=0){
        return;
    }

    if(mMapcanvas){
        mMapcanvas->zoomToFeatureIds(mVectorLayer, featureIds);
    }

    //高亮筛选出的内容
    this->hightLightFilteredFeatures(featureIds);
}

void QRSAGSQueryDialog::hightLightFilteredFeatures(const QgsFeatureIds &featureIds)
{
    //高亮筛选出的内容
    QgsFeatureIterator featureIterator = mVectorLayer->getFeatures(featureIds);
    QgsFeature feature;
    QList<QgsGeometry> geometryList;
    while ( featureIterator.nextFeature( feature ) )
    {
        if ( !feature.hasGeometry() )
            continue;
        geometryList << feature.geometry();
    }

    QgsWkbTypes::GeometryType geomType = QgsWkbTypes::geometryType( geometryList.at( 0 ).wkbType() );
    if(mRubberBand != nullptr){
        mRubberBand->reset(geomType);
    }else {
        mRubberBand = new QgsRubberBand(mMapcanvas, geomType );
    }

    for ( const QgsGeometry &geometry : geometryList )
        mRubberBand->addGeometry( geometry, mVectorLayer->crs());

    if ( geomType == QgsWkbTypes::LineGeometry || geomType == QgsWkbTypes::PointGeometry )
    {
        mRubberBand->setWidth( 2 );
        mRubberBand->setSecondaryStrokeColor( QColor( 255, 255, 255 ) );
    }
    if ( geomType == QgsWkbTypes::PointGeometry )
        mRubberBand->setIcon( QgsRubberBand::ICON_CIRCLE );

    QColor mapcanvasColor = mMapcanvas->selectionColor();
    QgsRenderContext context = QgsRenderContext::fromMapSettings( mMapcanvas->mapSettings() );
    QgsSymbolList symbols =mVectorLayer->renderer()->symbols(context);

    QColor color(255,255,255,255);
    if(symbols.size() >= 0){
        color = symbols.at(0)->color();
    }else {
        color = mapcanvasColor;
    }

    QColor featuresColor(255-color.red(), 255-color.green(), 255-color.blue(), 255);
    mRubberBand->setFillColor(featuresColor);
}

void QRSAGSQueryDialog::hightLightSelectedFeature(const QModelIndex &index)
{
    QgsFeatureId featureId = mFilterModel->rowToId(index);
    QgsFeature feature = mVectorLayer->getFeature(featureId);
    QgsGeometry geometry = feature.geometry();

    QgsWkbTypes::GeometryType geomType = QgsWkbTypes::geometryType( geometry.wkbType() );
    if(mSingleRubberBand != nullptr){
        mSingleRubberBand->reset(geomType);
    }else {
        mSingleRubberBand = new QgsRubberBand(mMapcanvas, geomType );
    }
    mSingleRubberBand = new QgsRubberBand(mMapcanvas, geomType );
    mSingleRubberBand->addGeometry(geometry, mVectorLayer->crs());

    if ( geomType == QgsWkbTypes::LineGeometry || geomType == QgsWkbTypes::PointGeometry )
    {
        mSingleRubberBand->setWidth( 2 );
        mSingleRubberBand->setSecondaryStrokeColor( QColor( 255, 255, 255 ) );
    }
    if ( geomType == QgsWkbTypes::PointGeometry )
        mSingleRubberBand->setIcon( QgsRubberBand::ICON_CIRCLE );

    QColor mapcanvasColor = mMapcanvas->selectionColor();
    QgsRenderContext context = QgsRenderContext::fromMapSettings( mMapcanvas->mapSettings() );
    QgsSymbolList symbols =mVectorLayer->renderer()->symbols(context);

    QColor color(255,255,255,255);
    if(symbols.size() >= 0){
        color = symbols.at(0)->color();
    }else {
        color = mapcanvasColor;
    }

    QColor featuresColor(qFloor((255-color.red())*0.8), qFloor((255-color.green())*0.8), qFloor((255-color.blue())*0.8), 255);
    mSingleRubberBand->setFillColor(featuresColor);
}

void QRSAGSQueryDialog::queryByRectanglePosition()
{
    QString rectangleWLon = ui->mRectangleWLonLineEdit->text();
    QString rectangleELon = ui->mRectangleELonLineEdit->text();
    QString rectangleNLat = ui->mRectangleNLatLineEdit->text();
    QString rectangleSLat = ui->mRectangleSLatLineEdit->text();
    if(!isDigitStr(rectangleWLon) || !isDigitStr(rectangleELon) || !isDigitStr(rectangleNLat) || !isDigitStr(rectangleSLat)){
        QMessageBox::warning(this, tr("Input Data: "), tr("Please check the input data, maybe it is not a number..."));
        return;
    }

    //获取所有的图层目标，遍历求交集
    QgsPointXY NWPointXY(rectangleWLon.toDouble(), rectangleNLat.toDouble());
    QgsPointXY NEPointXY(rectangleELon.toDouble(), rectangleNLat.toDouble());
    QgsPointXY SWPointXY(rectangleWLon.toDouble(), rectangleSLat.toDouble());
    QgsPointXY SEPointXY(rectangleELon.toDouble(), rectangleSLat.toDouble());
    QgsPolylineXY polylineXY;
    polylineXY.append(NWPointXY);
    polylineXY.append(NEPointXY);
    polylineXY.append(SEPointXY);
    polylineXY.append(SWPointXY);
    QgsGeometry polylineGeometry = QgsGeometry::fromPolylineXY(polylineXY);
    //    QgsGeometry polylineGeometry = QgsGeometry::fromPolylineXY(polygonXY);
    QgsFeatureIds featureIds = mVectorLayer->allFeatureIds();
    QgsFeatureIterator featureIterator = mVectorLayer->getFeatures(featureIds);
    QgsFeature feature;
    QgsFeatureIds filteredFeatureIds;
    while (featureIterator.nextFeature(feature)) {
        QgsGeometry geometry = feature.geometry();
        bool intersected = geometry.intersects(polylineGeometry);
        if(intersected){
            filteredFeatureIds.insert(feature.id());
        }
    }

    mFilterModel->setFilteredFeatures(filteredFeatureIds);
    mFilterModel->filteredFeatures();
    this->setFilterMode(QgsAttributeTableFilterModel::ShowFilteredList);
    this->zoomToCurrentFeature();
    //    this->hightLightFilteredFeatures(filteredFeatureIds);
}

void QRSAGSQueryDialog::queryByPointPosition()
{
    //构建需要查询的点
    QString pointLon = ui->mPointLonLineEdit->text();
    QString pointLat = ui->mPointLatLineEdit->text();

    if(!isDigitStr(pointLon) || !isDigitStr(pointLat)){
        QMessageBox::warning(this, tr("Input Data: "), tr("Please check the input data, maybe it is not a number..."));
        return;
    }

    //获取所有的图层目标，遍历求交集
    QgsPointXY pointXY(pointLon.toDouble(), pointLat.toDouble());
    QgsGeometry pointGeometry = QgsGeometry::fromPointXY(pointXY);
    QgsFeatureIds featureIds = mVectorLayer->allFeatureIds();
    QgsFeatureIterator featureIterator = mVectorLayer->getFeatures(featureIds);
    QgsFeature feature;
    QgsFeatureIds filteredFeatureIds;
    while (featureIterator.nextFeature(feature)) {
        QgsGeometry geometry = feature.geometry();
        bool intersected = geometry.intersects(pointGeometry);
        if(intersected){
            filteredFeatureIds.insert(feature.id());
        }
    }

    mFilterModel->setFilteredFeatures(filteredFeatureIds);
    mFilterModel->filteredFeatures();
    this->setFilterMode(QgsAttributeTableFilterModel::ShowFilteredList);
    this->zoomToCurrentFeature();

    //    this->hightLightFilteredFeatures(filteredFeatureIds);

}

void QRSAGSQueryDialog::pointPositionValueChanged(QString value)
{
    QString pointLon = ui->mPointLonLineEdit->text();
    QString pointLat = ui->mPointLatLineEdit->text();
    ui->mPointClearButton->setEnabled(!pointLon.isEmpty()||!pointLat.isEmpty());
}

void QRSAGSQueryDialog::rectanglePositionValueChanged(QString value)
{
    QString rectangleWLon = ui->mRectangleWLonLineEdit->text();
    QString rectangleELon = ui->mRectangleELonLineEdit->text();
    QString rectangleNLat = ui->mRectangleNLatLineEdit->text();
    QString rectangleSLat = ui->mRectangleSLatLineEdit->text();
    ui->mRectangleClearButton->setEnabled(!rectangleWLon.isEmpty()||!rectangleELon.isEmpty()||!rectangleNLat.isEmpty()||!rectangleSLat.isEmpty());
}

void QRSAGSQueryDialog::clearPointPosition(bool)
{
    ui->mPointLonLineEdit->text().clear();
    ui->mPointLatLineEdit->text().clear();

    this->setFilterMode(QgsAttributeTableFilterModel::ShowAll);
    if(this->mRubberBand != nullptr){
        this->mRubberBand->reset();
    }
    if(this->mSingleRubberBand != nullptr){
        this->mSingleRubberBand->reset();
    }

    mMapcanvas->zoomToFullExtent();
}

void QRSAGSQueryDialog::clearRectanglePosition(bool)
{
    ui->mRectangleWLonLineEdit->text().clear();
    ui->mRectangleELonLineEdit->text().clear();
    ui->mRectangleNLatLineEdit->text().clear();
    ui->mRectangleSLatLineEdit->text().clear();

    this->setFilterMode(QgsAttributeTableFilterModel::ShowAll);
    if(this->mRubberBand != nullptr){
        this->mRubberBand->reset();
    }
    if(this->mSingleRubberBand != nullptr){
        this->mSingleRubberBand->reset();
    }

    mMapcanvas->zoomToFullExtent();
}

void QRSAGSQueryDialog::closeDialog(bool)
{
    if(this->mRubberBand != nullptr){
        this->mRubberBand->reset();
    }
    if(this->mSingleRubberBand != nullptr){
        this->mSingleRubberBand->reset();
    }

    this->close();
}

void QRSAGSQueryDialog::setFilterMode(QgsAttributeTableFilterModel::FilterMode filterMode)
{
    // cleanup any existing connections
    switch (mFilterModel->filterMode())
    {
    case QgsAttributeTableFilterModel::ShowVisible:
        disconnect( mMapcanvas, &QgsMapCanvas::extentsChanged, this, &QRSAGSQueryDialog::extentChanged );
        disconnect( mFilterModel, &QgsAttributeTableFilterModel::visibleReloaded, this, &QRSAGSQueryDialog::filterChanged );
        break;
    case QgsAttributeTableFilterModel::ShowAll:
    case QgsAttributeTableFilterModel::ShowEdited:
    case QgsAttributeTableFilterModel::ShowFilteredList:
        disconnect( mFilterModel, &QgsAttributeTableFilterModel::featuresFiltered, this, &QRSAGSQueryDialog::filterChanged );
        disconnect( mFilterModel, &QgsAttributeTableFilterModel::filterError, this, &QRSAGSQueryDialog::filterError );
        break;

    case QgsAttributeTableFilterModel::ShowSelected:
        disconnect( mTableModel->layer(), &QgsVectorLayer::selectionChanged, this, &QRSAGSQueryDialog::updateSelectedFeatures );
        break;
    }

    QgsFeatureRequest r = mTableModel->request();
    bool needsGeometry = filterMode == QgsAttributeTableFilterModel::ShowVisible;

    bool requiresTableReload = ( r.filterType() != QgsFeatureRequest::FilterNone || !r.filterRect().isNull() ) // previous request was subset
            || ( needsGeometry && r.flags() & QgsFeatureRequest::NoGeometry ) // no geometry for last request
            || ( mTableModel->rowCount() == 0 ); // no features

    if ( !needsGeometry )
        r.setFlags( r.flags() | QgsFeatureRequest::NoGeometry );
    else
        r.setFlags( r.flags() & ~( QgsFeatureRequest::NoGeometry ) );
    r.setFilterFids( QgsFeatureIds() );
    r.setFilterRect( QgsRectangle() );
    r.disableFilter();

    // setup new connections and filter request parameters
    switch ( filterMode )
    {
    case QgsAttributeTableFilterModel::ShowVisible:
        connect( mMapcanvas, &QgsMapCanvas::extentsChanged, this, &QRSAGSQueryDialog::extentChanged );
        if ( mMapcanvas )
        {
            QgsRectangle rect = mMapcanvas->mapSettings().mapToLayerCoordinates( mVectorLayer, mMapcanvas->extent() );
            r.setFilterRect( rect );
        }
        connect( mFilterModel, &QgsAttributeTableFilterModel::visibleReloaded, this, &QRSAGSQueryDialog::filterChanged );
        break;

    case QgsAttributeTableFilterModel::ShowAll:
    case QgsAttributeTableFilterModel::ShowEdited:
    case QgsAttributeTableFilterModel::ShowFilteredList:
        connect( mFilterModel, &QgsAttributeTableFilterModel::featuresFiltered, this, &QRSAGSQueryDialog::filterChanged );
        connect( mFilterModel, &QgsAttributeTableFilterModel::filterError, this, &QRSAGSQueryDialog::filterError );
        break;

    case QgsAttributeTableFilterModel::ShowSelected:
        connect( mTableModel->layer(), &QgsVectorLayer::selectionChanged, this, &QRSAGSQueryDialog::updateSelectedFeatures );
        r.setFilterFids( mTableModel->layer()->selectedFeatureIds() );
        break;
    }

    if ( requiresTableReload )
    {
        //disconnect the connections of the current (old) filtermode before reload
        mFilterModel->disconnectFilterModeConnections();

        mTableModel->setRequest( r );
        whileBlocking(mTableModel->layerCache())->setCacheGeometry( needsGeometry );
        mTableModel->loadLayer();
    }

    //update filter model
    mFilterModel->setFilterMode( filterMode );
    emit filterChanged();
}




